package com.googlecode.restitory.gae.filter.wrapper;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import com.googlecode.restitory.gae.http.NamePairs;

public class RestitoryHttpServletRequestWrapper extends HttpServletRequestWrapper {

	private final NamePairs params = new NamePairs();
	private final HttpServletRequest r;
	private String contentType;
	private byte[] content;
	private String charactercEncoding;

	public RestitoryHttpServletRequestWrapper(HttpServletRequest request) {
		super(request);
		this.r = request;
		parseParams();
	}

	@SuppressWarnings("unchecked")
	private void parseParams() {
		Enumeration<String> names = r.getParameterNames();
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			String[] array = r.getParameterValues(name);
			for (String value : array) {
				params.add(name, value);
			}
		}
	}

	@Override
	public String getParameter(String name) {
		return params.getFirst(name);
	}

	@SuppressWarnings("rawtypes")
	@Override
	public Map getParameterMap() {
		return params.toMap();
	}

	@SuppressWarnings("rawtypes")
	@Override
	public Enumeration getParameterNames() {
		return Collections.enumeration(params.getNames());
	}

	@Override
	public String[] getParameterValues(String name) {
		return params.getAsArray(name);
	}

	public void removeParameter(String name) {
		params.remove(name);
	}

	public void setParameter(String name, String... values) {
		if (values.length == 0) {
			removeParameter(name);
		} else {
			params.set(name, Arrays.asList(values));
		}
	}

	@Override
	public String getQueryString() {
		return params.asQueryString();
	}

	public void removeAllParameters() {
		params.getPairs().clear();
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	public void setContent(byte[] content) {
		this.content = content;
	}

	@Override
	public String getContentType() {
		if (contentType == null) {
			return super.getContentType();
		}
		return contentType;
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		if (content == null) {
			return super.getInputStream();
		}
		return new ByteArrayServletInputStream(content);
	}

	@Override
	public BufferedReader getReader() throws IOException {
		throw new RuntimeException("not supported");
	}

	public void addParameter(String name, String value) {
		params.add(name, value);
	}

	@Override
	public String getCharacterEncoding() {
		if (charactercEncoding == null) {
			return super.getCharacterEncoding();
		}
		return charactercEncoding;
	}

	public void setCharactercEncoding(String charactercEncoding) {
		this.charactercEncoding = charactercEncoding;
	}

}
